package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.product.SkuInfoFeignClient;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    SkuInfoFeignClient skuInfoFeignClient;

    /**
     * 根据请求带来的信息，决定使用
     * 登陆了：用户购物车：cart:info:用户id
     * 没登陆：临时购物车：cart:info:userTempId
     *
     * @param request
     * @return
     */
    @Override
    public String determinCartKey(HttpServletRequest request) {
        //1、请求头中如果有userId,这个就是当前登录的用户id
        String userId = request.getHeader("userId");
        if (!StringUtils.isEmpty(userId)){
            //说明网关把userId透传过来了
            return RedisConst.CART_PREFIX + userId;
        }else{
            //未登录，就用临时购物车
            String userTempId = request.getHeader("userTempId");
            return RedisConst.CART_TEMP_PREFIX + userTempId;
        }
    }

    /**
     * 给购物车中添加指定商品
     * @param key
     * @param skuId
     * @param skuNum
     * @return
     */
    @Override
    public CartInfo addToCart(String key, Long skuId, Integer skuNum) {
        CartInfo result = null;

        /*
            {
                String: key是str
                Long: hashKey是Long
                String: hashValue是Str
            }
         */
        BoundHashOperations<String, String, String> hashOps = getCart(key);
        //用户购物车和临时购物车过期时间是不同的
        if (hashOps.hasKey(skuId.toString())){
            //redis购物车已经有这个商品，商品数量叠加
            //先获取这个商品信息
            String jsonStr = hashOps.get(skuId.toString());
            try {
                //从购物车获取到的商品,反序列化
                result = new ObjectMapper().readValue(jsonStr, CartInfo.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            Integer num = result.getSkuNum();
            //修改购物车对象
            result.setSkuNum(num + skuNum);
            //再次查询价格
            BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(skuId);
            result.setSkuPrice(skuPrice);
            String jsonStr1 = null;
            try {
                jsonStr1 = new ObjectMapper().writeValueAsString(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

            //限制购物车数量
            if (hashOps.size() <= 200){
                hashOps.put(skuId.toString(),jsonStr1);
            }else{
                //TODO 临时购物车合并也走这里，如果临时购物车合并的时候购物车数量超了，应该清除临时购物车，再抛异常

                throw new RuntimeException("购物车数量限制");
            }




        }else {
            //给购物车保存cartInfo(skuInfo)信息
            //skuId，远程查询sku详情
            SkuInfo skuInfo = skuInfoFeignClient.getSkuInfo(skuId);
            //给redis中保存的加入购物车的当前商品信息
            result = CartInfo.convertSkuInfoCart(skuInfo);
            BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(skuId);
            result.setCartPrice(skuPrice);
            //设置数量
            result.setSkuNum(skuNum);

            String jsonStr = null;
            try {
                jsonStr = new ObjectMapper().writeValueAsString(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

            //限制购物车数量
            if (hashOps.size() <= 200){
                hashOps.put(skuId.toString(),jsonStr);
            }else{
                //TODO 临时购物车合并也走这里，如果临时购物车合并的时候购物车数量超了，应该清除临时购物车，再抛异常

                throw new RuntimeException("购物车数量限制");
            }

            if (key.startsWith("cart:temp:")){
                redisTemplate.expire(key,RedisConst.TEMP_CART_EXPIRE, TimeUnit.SECONDS);
            }
        }
        return result;
    }

    /**
     * 获取购物车的全部列表
     * @return
     */
    @Override
    public List<CartInfo> listCart(String tempCartKey, String userCartKey) {

        List<CartInfo> result = null;

        /**
         * 1、如果用户登陆了，key:默认是登录用户，购物车是用户购物车
         * 但是还带了userTempId,代表没登录前用的临时车
         * 2、判断如果用户登录了，带了userTempId,购物车需要合并
         */
        if (!StringUtils.isEmpty(tempCartKey)){
            BoundHashOperations<String, String, String> cart = getCart(tempCartKey);
            if (cart.size() > 0){
                //临时购物车有数据，拿到购物车的所有数据
                result = getCartInfoList(tempCartKey);
            }
        }
        if (!StringUtils.isEmpty(userCartKey)){
            //说明用户登录了,把临时购物车的数据和用户的购物车合并
            if (!CollectionUtils.isEmpty(result)){
                //合并操作
                for (CartInfo tempCartInfo : result) {
                    //把临时购物车商品拿来添加到用户购物车中
                    addToCart(userCartKey,tempCartInfo.getSkuId(),tempCartInfo.getSkuNum());
                    //删除临时购物车
                    redisTemplate.delete(tempCartKey);
                }
            }
            //如果前面合并了，拿到的就是合并的结果
            result = getCartInfoList(userCartKey);
        }
        return result;
    }

    /**
     * 绑定redis
     * @param key
     * @return
     */
    private BoundHashOperations<String, String, String> getCart(String key){
        BoundHashOperations<String, String, String> hashOps = redisTemplate.boundHashOps(key);
        return hashOps;
    }

    private List<CartInfo> getCartInfoList(String key){
        List<CartInfo> cartInfos = new ArrayList<>();
        //拿到购物车
        BoundHashOperations<String, String, String> cart = getCart(key);

        List<String> values = cart.values();
        if (!CollectionUtils.isEmpty(values)){
            //redis在这个购物车有数据
            for (String skuJson : values) {
                CartInfo cartInfo = null;
                try {
                    cartInfo = new ObjectMapper().readValue(skuJson, CartInfo.class);
                    cartInfo.setCreateTime(null);
                    cartInfo.setUpdateTime(null );
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                cartInfos.add(cartInfo);
            }
        }
        return cartInfos;
    }

    @Override
    public String userCartKey(HttpServletRequest request) {
        String userId = request.getHeader("userId");
        if (!StringUtils.isEmpty(userId)){
            return RedisConst.CART_PREFIX + userId;
        }
        return null;
    }

    @Override
    public String tempCartKey(HttpServletRequest request) {
        String userTempId = request.getHeader("userTempId");
        if (!StringUtils.isEmpty(userTempId)){
            return RedisConst.CART_TEMP_PREFIX + userTempId;
        }
        return null;
    }

    /**
     * 选中购物车
     * @param key
     * @param skuId
     * @param checked
     */
    @Override
    public void ajaxCheckCart(String key, Long skuId, Integer checked) {
        ObjectMapper objectMapper = new ObjectMapper();
        BoundHashOperations<String, String, String> cart = getCart(key);
        String json = cart.get(skuId.toString());
        CartInfo cartInfo = null;
        try {
            cartInfo = objectMapper.readValue(json, CartInfo.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //设置状态
        cartInfo.setIsChecked(checked);
        String strJson = null;
        try {
            strJson = objectMapper.writeValueAsString(cartInfo);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        cart.put(skuId.toString(),strJson);
    }

    /**
     * 删除购物车中的商品
     * @param key
     * @param skuId
     */
    @Override
    public void ajaxDeleteCart(String key, Long skuId) {
        BoundHashOperations<String, String, String> cart = getCart(key);
        cart.delete(skuId.toString());
    }

    /**
     * 获取购物车已选中的商品
     * @return
     */
    @Override
    public List<CartInfo> getListCheckCartInfo(HttpServletRequest request) {
        ObjectMapper objectMapper = new ObjectMapper();

        List<CartInfo> checkedList = new ArrayList<>();
        String key = determinCartKey(request);
        BoundHashOperations<String, String, String> cart = getCart(key);

        //返回的是购物车中的商品的json
        List<String> values = cart.values();
        if (!CollectionUtils.isEmpty(values)){
            for (String cartinfo : values) {
                CartInfo cartInfo = null;
                try {
                    cartInfo = objectMapper.readValue(cartinfo, CartInfo.class);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                if (cartInfo.getIsChecked() == 1){
                    //被选中
                    checkedList.add(cartInfo);
                }
            }
        }

        return checkedList;
    }

    @Override
    public void ajaxDeleteCartItemBatch(String key, List<String> skuIds) {
        BoundHashOperations<String, String, String> cart = getCart(key);
        String[] strings = skuIds.toArray(new String[skuIds.size()]);
        cart.delete(strings);
    }
}
